前面我們已經寫了幾個 API 昨天我們也為了實現 JWT 的功能而使用了套件內的 ViewSet。目前為止我們還可以透過文件或是寫程式的記憶力去知道 API 會需要什麼傳入並回傳哪個格式,但隨著 API 越來越多後我們可能會記不清楚。而且如果其他要使用這個 API 我們也需要提供一份文件才能讓他們方便使用,所以讓我們為我們的 API 加上文件吧!
而目前常被用來當作 API 文件的是一個名為 OpenAPI 的格式,他會描述我們有哪些 API 還有傳入傳出的格式,搭配一些工具例如 Swagger 或是 Redoc 就可以產生一個 API 文件了
前面我們提到格式會使用 OpenAPI 這個格式,在一些情況我們需要自己寫,這樣才能讓工具正確的產生我們的文件,但是自己寫實在是太浪費時間了,所以我們要借助一個套件,他會自動的列出我們的 API 並根據我們設定的序列化產生對應的輸入輸出格式。
我們這次會使用的套件是 drf-spectacular 他會協助我們從程式碼自動的產出 OpenAPI 格式
poetry add drf-spectacular
P.S. 以前大家可能比較習慣使用的套件是 drf-yasg 但他產生出來的格式是 OpenAPI 2.0 而 drf-spectacular 產出來的是 3.0 所以我們會使用新的。
安裝完成後別忘了把 APP 加入 server/settings.py
中
# ...... 以上省略 ......
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"rest_framework",
"rest_framework_simplejwt",
+ "drf_spectacular",
"server.app.common",
"server.app.todo",
]
# ...... 以下省略 ......
我們已經把套件安裝好了,接下來我們要進行設定,打開 server/settings.py
並依照下方方式修改
# ...... 以上省略 ......
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework_simplejwt.authentication.JWTAuthentication",
],
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework.permissions.IsAuthenticated",
],
+ "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
}
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": datetime.timedelta(minutes=5),
"REFRESH_TOKEN_LIFETIME": datetime.timedelta(days=1),
"ROTATE_REFRESH_TOKENS": True,
}
+SPECTACULAR_SETTINGS = {
+ "TITLE": "DRF Todo List",
+ "DESCRIPTION": "This is a todo list for DRF practice.",
+ "VERSION": "1.0.0",
+ "SERVE_INCLUDE_SCHEMA": False,
+}
以上設定我們告訴 DRF 我們的 Schema class 要使用我們剛剛安裝的套件提供的 AutoSchema
並在 SPECTACULAR_SETTINGS 中設定文件標題(title)、說明(description)、版本(version)以及是否隱藏 Schema(後面會提到)
# ...... 以上省略 ......
from django.contrib import admin
from django.urls import include, path
+from drf_spectacular import views as doc_views
from rest_framework import routers
from rest_framework_simplejwt import views as jwt_views
from server.app.common import views as common_views
from server.app.todo import views as todo_views
router = routers.SimpleRouter(trailing_slash=False)
router.register("todo/tasks", todo_views.TaskViewSet)
router.register("todo/tags", todo_views.TagViewSet)
urlpatterns = [
path("admin/", admin.site.urls),
path("health", common_views.HealthView.as_view()),
path("api/token", jwt_views.TokenObtainPairView.as_view()),
path("api/token/refresh", jwt_views.TokenRefreshView.as_view()),
+ path("api/schema.json", doc_views.SpectacularJSONAPIView.as_view(), name="schema"),
+ path("api/swagger/", doc_views.SpectacularSwaggerView.as_view()),
+ path("api/redoc/", doc_views.SpectacularRedocView.as_view()),
path("api/", include(router.urls)),
]
在這邊我們設定了三個路由
/api/schema.json
:這個路由會提供 OpenAPI Schema 的 JSON 格式,前面的 SERVE_INCLUDE_SCHEMA
就是設定是否在文件中隱藏這個 API,如果設定為 False
文件中就不會出現這個路由。而我們在設定這個路由時有給他一個名字 schema
因為等等的工具會使用它。/api/swagger/
:這個路由會產生一個 Swagger 的網頁畫面,他會使用 /api/schema.json
提供的內容產生對應的文件(這就為什麼我們在設定前面那個路由後需要給他名字的原因)。/api/redoc/
:這個路由與 Swagger 差不多,只是畫面變成 Redoc 格式。現在我們已經設定好了所有設定,現在我們要開啟 server(別忘了啟動虛擬環境)
python manage.py runserver
接著使用瀏覽器訪問下方三個網址
今天我們透過套件的協助我們就建立了文件,這樣前端或是其他人需要使用這個 API 時就可以依照文件的格式使用,而且我們的文件當我們修改 API 時也會產生對應的變化,這樣就不用費心再去修改文件。
結束前別忘了檢查一下今天的程式碼有沒有問題,並排版好喔。
ruff check --fix .
black .
pyright .
今天的內容就到這邊了,讓我們期待明天的內容吧。
P.S. 今天的檔案更新可以參考我的 Git Commit 大家可以搭配服用